home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2009 February / PCWFEB09.iso / Software / Linux / Kubuntu 8.10 / kubuntu-8.10-desktop-i386.iso / casper / filesystem.squashfs / usr / share / hplip / dat2drv.py < prev    next >
Text File  |  2008-10-13  |  25KB  |  828 lines

  1. #!/usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3. #
  4. # (c) Copyright 2008 Hewlett-Packard Development Company, L.P.
  5. #
  6. # This program is free software; you can redistribute it and/or modify
  7. # it under the terms of the GNU General Public License as published by
  8. # the Free Software Foundation; either version 2 of the License, or
  9. # (at your option) any later version.
  10. #
  11. # This program is distributed in the hope that it will be useful,
  12. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. # GNU General Public License for more details.
  15. #
  16. # You should have received a copy of the GNU General Public License
  17. # along with this program; if not, write to the Free Software
  18. # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
  19. #
  20. # Author: Don Welch
  21. #
  22.  
  23. __version__ = "2.1"
  24. __title__ = 'DAT to DRV.IN converter. Also creates Foomatic XML files.'
  25. __doc__ = "Create DRV.IN file and Foomatic XML files from MODELS.DAT data. Processes all *.in.template files in prnt/drv directory."
  26.  
  27. import os
  28. os.putenv("HPLIP_BUILD", "1")
  29.  
  30. # Std Lib
  31. import os.path
  32. import sys
  33. import getopt
  34. import re
  35. from xml.dom.minidom import Document, parse, parseString
  36. from types import StringType, UnicodeType
  37. import string
  38.  
  39. # Local
  40. from base.g import *
  41. from base import utils, tui, models
  42. #from prnt import printable_areas
  43.  
  44. # Globals
  45. errors = 0
  46. count = 0
  47. enc = 'utf-8'
  48.  
  49. models_dict = {}
  50. norm_models = {} # { 'norm'd model' : ( 'model', type, has_scanner ), ... }
  51. norm_models_keys = {}
  52. model_dat = None
  53. total_models = 0
  54. sorted_category_models = {}
  55. unsupported_models = []
  56.  
  57. pat_prod_num = re.compile("""(\d+)""", re.I)
  58. pat_template = re.compile("""^(\s*)//\s*<%(\S+)%>""", re.I)
  59. pat_template2 = re.compile("""^\s*<%(\S+)%>""", re.I)
  60.  
  61.  
  62. USAGE = [(__doc__, "", "name", True),
  63.          ("Usage: dat2drv.py [OPTIONS]", "", "summary", True),
  64.          utils.USAGE_OPTIONS,
  65.          ("Verbose mode:", "-v or --verbose", "option", False),
  66.          ("Quiet mode:", "-q or --quiet", "option", False),
  67.          utils.USAGE_LOGGING1, utils.USAGE_LOGGING2,
  68.          utils.USAGE_HELP,
  69.         ]
  70.  
  71. def usage(typ='text'):
  72.     if typ == 'text':
  73.         utils.log_title(__title__, __version__)
  74.  
  75.     utils.format_text(USAGE, typ, __title__, 'drv2xml.py', __version__)
  76.     sys.exit(0)
  77.  
  78.     
  79.     
  80. def _encode(v):
  81.     if isinstance(v, UnicodeType):
  82.         v = v.encode(enc)
  83.     return v
  84.     
  85.     
  86.  
  87. class XMLElement:
  88.     def __init__(self, doc, el):
  89.         self.doc = doc
  90.         self.el = el
  91.  
  92.     def __getitem__(self, name):
  93.         a = self.el.getAttributeNode(name)
  94.         if a:
  95.             return _encode(a.value)
  96.         return None
  97.  
  98.     def __setitem__(self, name, value):
  99.         self.el.setAttribute(name, _encode(value))
  100.  
  101.     def __delitem__(self, name):
  102.         self.el.removeAttribute(name)
  103.  
  104.     def __str__(self):
  105.         return _encode(self.doc.toprettyxml())
  106.  
  107.     def toString(self):
  108.         return _encode(self.doc.toxml())
  109.  
  110.     def _inst(self, el):
  111.         return XMLElement(self.doc, el)
  112.  
  113.     def get(self, name, default=None):
  114.         a = self.el.getAttributeNode(name)
  115.         if a:
  116.             return _encode(a.value)
  117.         return _encode(default)
  118.  
  119.     def add(self, tag, **kwargs):
  120.         el = self.doc.createElement(tag)
  121.         for k, v in kwargs.items():
  122.             el.setAttribute(k, _encode(str(v)))
  123.         return self._inst(self.el.appendChild(el))
  124.  
  125.     def addText(self, data):
  126.         return self._inst(
  127.             self.el.appendChild(
  128.                 self.doc.createTextNode(_encode(data))))
  129.  
  130.     def addComment(self, data):
  131.         return self._inst(
  132.             self.el.appendChild(
  133.                 self.doc.createComment(data)))
  134.  
  135.     def getText(self, sep=" "):
  136.         rc = []
  137.         for node in self.el.childNodes:
  138.             if node.nodeType == node.TEXT_NODE:
  139.                 rc.append(node.data)
  140.         return _encode(string.join(rc, sep))
  141.  
  142.     def getAll(self, tag):
  143.         return map(self._inst, self.el.getElementsByTagName(tag))
  144.  
  145.  
  146. class XMLDocument(XMLElement):
  147.  
  148.     def __init__(self, tag=None, **kwargs):
  149.         self.doc  = Document()
  150.         XMLElement.__init__(self, self.doc, self.doc)
  151.         if tag:
  152.             self.el = self.add(tag, **kwargs).el
  153.  
  154.     def parse(self, d):
  155.         self.doc = self.el = parse(d)
  156.         return self
  157.  
  158.     def parseString(self, d):
  159.         self.doc = self.el = parseString(_encode(d))
  160.         return self
  161.     
  162.  
  163.  
  164.         
  165. def fixFileName(model):
  166.     if model.startswith('hp_'):
  167.         model = model.replace('hp_', 'hp-')
  168.     
  169.     elif model.startswith('apollo_'):
  170.         model = model.replace('apollo_', 'apollo-')
  171.         
  172.     elif not model.startswith('hp-'):
  173.         model = 'hp-' + model
  174.     
  175.         
  176.     return model
  177.  
  178.     
  179. def categorize2(m):
  180.     is_aio = (models_dict[m]['scan-type'] != SCAN_TYPE_NONE or
  181.         models_dict[m]['copy-type'] != COPY_TYPE_NONE or
  182.         models_dict[m]['fax-type'] != FAX_TYPE_NONE)
  183.  
  184.     if "deskjet" in m or \
  185.         ("color" in m and "inkjet" in m) or \
  186.         m.startswith("dj") or \
  187.         m.startswith("cp"):
  188.  
  189.         if is_aio:
  190.             i = MODEL_TYPE2_DESKJET_AIO
  191.         else:
  192.             i = MODEL_TYPE2_DESKJET
  193.  
  194.     elif "photosmart" in m:
  195.         i = MODEL_TYPE2_PHOTOSMART
  196.  
  197.     elif "officejet" in m:
  198.         i = MODEL_TYPE2_OFFICEJET
  199.  
  200.     elif "psc" in m or \
  201.         "printer_scanner_copier" in m:
  202.  
  203.         i = MODEL_TYPE2_PSC
  204.  
  205.     elif "laserjet" in m:
  206.         if "color" in m:
  207.             i = MODEL_TYPE2_COLOR_LASERJET
  208.         else:
  209.             i = MODEL_TYPE2_LASERJET
  210.  
  211.     elif "mopier" in m:
  212.         i = MODEL_TYPE2_LASERJET
  213.  
  214.     elif "business" in m and \
  215.         "inkjet" in m:
  216.  
  217.         i = MODEL_TYPE2_BIJ
  218.  
  219.     elif "edgeline" in m:
  220.         i = MODEL_TYPE2_EDGELINE
  221.  
  222.     elif "apollo" in m:
  223.         i = MODEL_TYPE2_APOLLO
  224.  
  225.     else: # Other
  226.         i = MODEL_TYPE2_OTHER
  227.  
  228.     return (m, i, models_dict[m])
  229.  
  230.  
  231. def sort_product(x, y):
  232.     try:
  233.         _x = int(pat_prod_num.search(x).group(1))
  234.     except (TypeError, AttributeError):
  235.         _x = 0
  236.  
  237.     try:
  238.         _y = int(pat_prod_num.search(y).group(1))
  239.     except (TypeError, AttributeError):
  240.         _y = 0
  241.  
  242.     if not _x and not _y:
  243.         return cmp(x, y)
  244.  
  245.     return cmp(_x, _y)
  246.  
  247.  
  248. def sort_product2(x, y): # sort key is first element of tuple
  249.     return sort_product(x[0], y[0])
  250.  
  251.     
  252. def load_models(unreleased=True):
  253.     global models_dict
  254.     global norm_models
  255.     global norm_models_keys
  256.     global model_dat
  257.     global total_models
  258.     global sorted_category_models
  259.     global unsupported_models
  260.  
  261.     models_dict = model_dat.read_all_files(unreleased)
  262.  
  263.     log.debug("Raw models:")
  264.  
  265.     for m in models_dict:
  266.         nm = models.normalizeModelUIName(m)
  267.         models_dict[m]['norm_model'] = nm
  268.         models_dict[m]['case_models'] = []
  269.  
  270.         i, case_models = 1, []
  271.         while True:
  272.             try:
  273.                 cm = models.normalizeModelUIName(models_dict[m]['model%d' % i])
  274.             except KeyError:
  275.                 break
  276.  
  277.             case_models.append(cm)
  278.             i+= 1
  279.  
  280.         if not case_models:
  281.             case_models = [nm]
  282.  
  283.         models_dict[m]['case_models'] = case_models[:]
  284.         cat = categorize2(m)
  285.         models_dict[m]['category'] = cat
  286.  
  287.         for c in case_models:
  288.             norm_models[c] =  cat
  289.  
  290.             if models_dict[m]['support-type'] == SUPPORT_TYPE_NONE:
  291.                 unsupported_models.append((c, m))
  292.  
  293.     norm_models_keys = norm_models.keys()
  294.     norm_models_keys.sort(lambda x, y: sort_product(x, y))
  295.  
  296.     unsupported_models.sort(lambda x, y: sort_product2(x, y))
  297.  
  298.     total_models = len(norm_models)
  299.  
  300.     #log.info("Loaded %d models." % total_models)
  301.     
  302.     
  303.     
  304.     
  305. def main(args):
  306.     global errors
  307.     global model_dat
  308.     line_num = 0
  309.     log.set_module("dat2drv.py")
  310.     cur_path = os.path.realpath(os.path.normpath(os.getcwd()))
  311.     dat_path = os.path.join(cur_path, 'data', 'models')
  312.     model_dat = models.ModelData(dat_path)
  313.     load_models()
  314.     
  315.     
  316.     
  317.     verbose = False
  318.     quiet = False
  319.     
  320.     try:
  321.         opts, args = getopt.getopt(args, 'd:l:ho:vq',
  322.                                    ['logging=', 'help',
  323.                                     'help-rest', 'help-man', 
  324.                                     'drv=', 'output=',
  325.                                     'verbose', 'quiet'])
  326.     except getopt.GetoptError, e:
  327.         log.error(e.msg)
  328.         usage()
  329.         sys.exit(0)
  330.  
  331.     log_level = 'info'
  332.     if os.getenv("HPLIP_DEBUG"):
  333.         log.set_level('debug')
  334.  
  335.     for o, a in opts:
  336.         if o in ('-h', '--help'):
  337.             usage()
  338.  
  339.         elif o == '--help-rest':
  340.             usage('rest')
  341.  
  342.         elif o == '--help-man':
  343.             usage('man')
  344.             
  345.         elif o in ('-v', '--verbose'):
  346.             verbose = True
  347.  
  348.         elif o in ('-q', '--quiet'):
  349.             quiet = True
  350.  
  351.         elif o in ('-l', '--logging'):
  352.             log.set_level(a.lower().strip())
  353.  
  354.  
  355.     if not quiet:
  356.         utils.log_title(__title__, __version__)
  357.     
  358.     drv_dir = os.path.join(cur_path, 'prnt', 'drv')
  359.     
  360.     errors = []
  361.     warns = []
  362.     notes = []
  363.     
  364.     for template_file in utils.walkFiles(drv_dir, recurse=False, abs_paths=True, 
  365.         return_folders=False, pattern='*.in.template'):
  366.         
  367.         basename = os.path.basename(template_file).split('.')[0]
  368.         
  369.         # Output
  370.         drv_in_file = os.path.join(cur_path, 'prnt', 'drv', '%s.drv.in' % basename)
  371.         
  372.         # XML output (per model)
  373.         output_path = os.path.join(cur_path, 'prnt', 'drv', 'foomatic_xml', basename)
  374.         
  375.         # XML Output (master driver list)
  376.         driver_path = os.path.join(cur_path, 'prnt', 'drv', 'foomatic_xml', basename, '%s.xml' % basename)
  377.         
  378.         log.info("Working on %s file..." % basename)
  379.         log.info("Input file: %s" % template_file)
  380.         log.info("Output file: %s" % drv_in_file)
  381.         log.info("Output XML directory: %s" % output_path)
  382.         log.info("Output driver XML file: %s" % driver_path)
  383.  
  384.         
  385.         
  386.         # CREATE DRV.IN FILE
  387.         
  388.         log.info("Processing %s.drv.in.template..." % basename)
  389.         tui.update_spinner()
  390.         
  391.         template_classes = []
  392.         
  393.         template_file_f = open(template_file, 'r')
  394.         drv_in_file_f = open(drv_in_file, 'w')
  395.         
  396.         models_placement = {}
  397.         for m in models_dict:
  398.             models_placement[m] = 0
  399.             
  400.         line = 0
  401.         
  402.         for x in template_file_f:
  403.             if verbose:
  404.                 log.info(x.strip())
  405.                 
  406.             line += 1
  407.             tui.update_spinner()
  408.             drv_in_file_f.write(x)
  409.             match = pat_template.match(x)
  410.             if match is not None:
  411.                 matches = []
  412.                 
  413.                 indent = match.group(1)
  414.                 indent2 = ' '*(len(indent)+2)
  415.                 
  416.                 classes = match.group(2).split(':')
  417.                 tech_class = classes[0]
  418.                 
  419.                 if tech_class not in models.TECH_CLASSES:
  420.                     errors.append("(%s:line %d) Invalid tech-class (%s): %s" % (basename, line, tech_class, x.strip()))
  421.                     continue
  422.                 
  423.                 template_classes.append(tech_class)
  424.                 
  425.                 tech_subclass = classes[1:]
  426.                 
  427.                 ok = True
  428.                 for sc in tech_subclass:
  429.                     if sc not in models.TECH_SUBCLASSES:
  430.                         errors.append("(%s:line %d) Invalid tech-subclass (%s): %s" % (basename, line, sc, x.strip()))
  431.                         ok = False
  432.                         
  433.                 if not ok:
  434.                     continue
  435.                 
  436.                 for m in models_dict:
  437.                     if tech_class in models_dict[m]['tech-class']:
  438.                         include = True
  439.                         
  440.                         for sc in models_dict[m]['tech-subclass']:
  441.                             if not sc in tech_subclass:
  442.                                 include = False
  443.                                 break
  444.                             
  445.                         if include:
  446.                             models_placement[m] += 1
  447.                             matches.append(m)
  448.                             
  449.                     
  450.                 if matches:
  451.                     matches.sort(lambda x, y: sort_product(x, y))
  452.                     
  453.                     for p in matches:
  454.                         
  455.                         if verbose:
  456.                             log.info("(%s) Adding section for model: %s" % (basename, p))
  457.                         
  458.                         drv_in_file_f.write("%s{\n" % indent)
  459.                         
  460.                         drv_in_file_f.write('%sModelName "%s Foomatic/hpijs"\n' % 
  461.                             (indent2, models_dict[p]['norm_model']))
  462.                         
  463.                         if 'apollo' in p.lower():
  464.                             devid = "MFG:APOLLO;MDL:%s;DES:%s;" % (p, p)
  465.                         
  466.                         else:
  467.                             devid = "MFG:HP;MDL:%s;DES:%s;" % (p, p)
  468.                         
  469.                         drv_in_file_f.write('%sAttribute "1284DeviceID" "" "%s"\n' % (indent2, devid))
  470.  
  471.                         if len(models_dict[p]['tech-class']) > 1: # and 'Postscript' not in models_dict[p]['tech-class']:
  472.                             drv_in_file_f.write('%sPCFileName "%s-hpijs-%s.ppd"\n' % 
  473.                                 (indent2, fixFileName(p), models.TECH_CLASS_PDLS[tech_class]))
  474.                         
  475.                         elif tech_class != 'Postscript':
  476.                             drv_in_file_f.write('%sPCFileName "%s-hpijs.ppd"\n' % (indent2, fixFileName(p)))
  477.                         
  478.                         else:
  479.                             drv_in_file_f.write('%sPCFileName "%s-ps.ppd"\n' % (indent2, fixFileName(p)))
  480.                             
  481.                         for c in models_dict[p]['case_models']:
  482.                             drv_in_file_f.write('%sAttribute "Product" "" "%s"\n' % (indent2, c))
  483.  
  484.                         drv_in_file_f.write("%s}\n" % indent)
  485.                         
  486.                 else:
  487.                     errors.append("(%s:line %d) No models matched the specified classes on line: %s" % (basename, line, x.strip()))
  488.                         
  489.             else:
  490.                 match = pat_template2.match(x)
  491.                 if match is not None:
  492.                     errors.append("(%s:line %d) Malformed line: %s (missing initial //)" % (basename, line, x.strip()))
  493.                 
  494.  
  495.         template_file_f.close()
  496.         drv_in_file_f.close()
  497.         tui.cleanup_spinner()
  498.       
  499.         for tc in models.TECH_CLASSES:
  500.             if tc.lower() in ('undefined', 'postscript', 'unsupported'):
  501.                 continue
  502.                 
  503.             if tc not in template_classes:
  504.                 errors.append("(%s) Section <%%%s:...%%> not found." % (basename, tc))
  505.         
  506.             
  507.         # OUTPUT XML FILES
  508.         
  509.         if not os.path.exists(output_path):
  510.             os.makedirs(output_path)
  511.             
  512.         if os.path.exists(driver_path):
  513.             os.remove(driver_path)
  514.  
  515.         files_to_delete = []
  516.         for f in utils.walkFiles(output_path, recurse=True, abs_paths=True, return_folders=False, pattern='*'):
  517.             files_to_delete.append(f)
  518.             
  519.         for f in files_to_delete:
  520.             os.remove(f)
  521.         
  522.         driver_f = file(driver_path, 'w')
  523.  
  524.         driver_doc = XMLDocument("driver", id="driver/%s" % basename)
  525.         name_node = driver_doc.add("name")
  526.         name_node.addText(basename)
  527.         url_node = driver_doc.add("url")
  528.         url_node.addText("http://hplip.sourceforge.net/")
  529.         supplier_node = driver_doc.add("supplier")
  530.         supplier_node.addText("Hewlett-Packard")
  531.         mfg_node = driver_doc.add("manufacturersupplied")
  532.         mfg_node.addText("HP|Apollo")
  533.         lic_node = driver_doc.add("license")
  534.         lic_node.addText("BSD/GPL/MIT")
  535.         driver_doc.add("freesoftware")
  536.         support_node = driver_doc.add("supportcontact", level="voluntary", url="https://launchpad.net/hplip")
  537.         support_node.addText("HPLIP Support at Launchpad.net")
  538.         shortdesc_node = driver_doc.add("shortdescription")
  539.         shortdesc_en_node = shortdesc_node.add("en")
  540.         shortdesc_en_node.addText("HP's IJS driver for most of their non-PostScript printers")
  541.         func_node = driver_doc.add("functionality")
  542.         maxresx_node = func_node.add("maxresx")
  543.         maxresx_node.addText("1200")
  544.         maxresy_node = func_node.add("maxresy")
  545.         maxresy_node.addText("1200")
  546.         func_node.add("color")
  547.         exec_node = driver_doc.add("execution")
  548.         exec_node.add("nopjl")
  549.         exec_node.add("ijs")
  550.         proto_node = exec_node.add("prototype")
  551.         proto_node.addText("gs -q -dBATCH -dPARANOIDSAFER -dQUIET -dNOPAUSE -sDEVICE=ijs -sIjsServer=hpijs%A%B%C -dIjsUseOutputFD%Z -sOutputFile=- -")
  552.         comments_node = driver_doc.add("comments")
  553.         comments_en_node = comments_node.add("en")
  554.         comments_en_node.addText("")
  555.         
  556.         printers_node = driver_doc.add("printers")
  557.         
  558.         for m in models_dict:
  559.             if 'apollo' in m.lower():
  560.                 make = 'APOLLO'
  561.             else:
  562.                 make = 'HP'
  563.                 
  564.             if 'apollo' in m.lower():
  565.                 ieee1284 = "MFG:APOLLO;MDL:%s;DES:%s;" % (m, m)
  566.             
  567.             else:
  568.                 ieee1284 = "MFG:HP;MDL:%s;DES:%s;" % (m, m)
  569.                 
  570.             postscriptppd = ''
  571.             if 'Postscript' in models_dict[m]['tech-class']:
  572.                 postscriptppd = "%s-ps.ppd" % fixFileName(m)
  573.                 
  574.             fixed_model = m.replace(' ', '_')
  575.             
  576.             if fixed_model.startswith('hp_'):
  577.                 fixed_model = fixed_model.replace('hp_', 'hp-')
  578.             
  579.             elif fixed_model.startswith('apollo_'):
  580.                 fixed_model = fixed_model.replace('apollo_', 'apollo-')
  581.                 
  582.             else:
  583.                 fixed_model = 'hp-' + fixed_model
  584.                 
  585.             stripped_model = m
  586.             if stripped_model.startswith('hp '):
  587.                 stripped_model = stripped_model.replace('hp ', '')
  588.             
  589.             
  590.             # Output to the per-model XML file
  591.             outputModel(m, fixed_model, stripped_model, make, postscriptppd, ieee1284, output_path, verbose)
  592.             
  593.             # Output to driver master XML file
  594.             outputDriver(m, fixed_model, stripped_model, make, printers_node, verbose)
  595.             
  596.         
  597.         driver_f.write(str(driver_doc))
  598.         driver_f.close()         
  599.         
  600.         # Make sure all models ended up in drv.in file
  601.         log.info("Checking for errors...")
  602.         tui.update_spinner()
  603.         
  604.         for m in models_dict:
  605.             tui.update_spinner()
  606.             tc = models_dict[m]['tech-class']
  607.             st = models_dict[m]['support-type']
  608.             
  609.             if not tc or 'Undefined' in tc:
  610.                 if st:
  611.                     errors.append('(%s) Invalid tech-class for model %s ("Undefined" or missing)' % (basename, m))
  612.                 else:
  613.                     warns.append('(%s) Invalid tech-class for unsupported model %s ("Undefined" or missing)' % (basename, m))
  614.         
  615.             else:
  616.                 if not models_placement[m] and st and \
  617.                     len(tc) == 1 and 'Postscript' not in tc:
  618.                     
  619.                     sects = []
  620.                     for tc in models_dict[m]['tech-class']:
  621.                         for sc in models_dict[m]['tech-subclass']:
  622.                             sects.append(sc)
  623.                             
  624.                     errors.append("(%s) Model '%s' did not have a matching section. Needed section: <%%%s:%s%%>" % 
  625.                         (basename, m, tc, ':'.join(sects)))
  626.                             
  627.                 if len(tc) == 1 and 'Postscript' in tc:
  628.                     notes.append("(%s) Postscript-only model %s was not included in DRV file." % (basename, m))
  629.                     
  630.         tui.cleanup_spinner()
  631.     
  632.         # end for 
  633.     
  634.     if not quiet or verbose:
  635.         if notes:
  636.             tui.header("NOTES")
  637.             for n in notes:
  638.                 log.note(n)
  639.                 
  640.         if warns:
  641.             tui.header("WARNINGS")
  642.             for w in warns:
  643.                 log.warn(w)
  644.                 
  645.         if errors:
  646.             tui.header("ERRORS")
  647.             for e in errors:
  648.                 log.error(e)
  649.                 
  650.     else:
  651.         if warns:
  652.             log.warn("%d warnings" % len(warns))
  653.             
  654.         if errors:
  655.             log.error("%d errors" % len(errors))
  656.             
  657.             
  658. def parseDeviceID(device_id):
  659.     d= {}
  660.     x = [y.strip() for y in device_id.strip().split(';') if y]
  661.  
  662.     for z in x:
  663.         y = z.split(':')
  664.         try:
  665.             d.setdefault(y[0].strip(), y[1])
  666.         except IndexError:
  667.             d.setdefault(y[0].strip(), None)
  668.  
  669.     d.setdefault('MDL', '')
  670.     d.setdefault('SN',  '')
  671.  
  672.     if 'MODEL' in d:
  673.         d['MDL'] = d['MODEL']
  674.         del d['MODEL']
  675.  
  676.     if 'SERIAL' in d:
  677.         d['SN'] = d['SERIAL']
  678.         del d['SERIAL']
  679.  
  680.     elif 'SERN' in d:
  681.         d['SN'] = d['SERN']
  682.         del d['SERN']
  683.  
  684.     if d['SN'].startswith('X'):
  685.         d['SN'] = ''
  686.  
  687.     return d
  688.     
  689.     
  690. def outputModel(model, fixed_model, stripped_model, make, postscriptppd, ieee1284, output_path, verbose=False):
  691.     global errors
  692.     global count
  693.     
  694.     count += 1
  695.     
  696. ##    fixed_model = model.replace(' ', '_')
  697. ##    
  698. ##    if fixed_model.startswith('hp_'):
  699. ##        fixed_model = fixed_model.replace('hp_', 'hp-')
  700. ##    
  701. ##    elif fixed_model.startswith('apollo_'):
  702. ##        fixed_model = fixed_model.replace('apollo_', 'apollo-')
  703. ##        
  704. ##    else:
  705. ##        fixed_model = 'hp-' + fixed_model
  706. ##        
  707. ##    stripped_model = model
  708. ##    if stripped_model.startswith('hp '):
  709. ##        stripped_model = stripped_model.replace('hp ', '')
  710.         
  711.     
  712.     output_filename = os.path.join(output_path, fixed_model+".xml")
  713.     
  714.     if verbose:
  715.         log.info("\n\n%s:" % output_filename)
  716.     
  717.     output_f = file(output_filename, 'w')
  718.     
  719.     doc = XMLDocument("printer", id="printer/%s" % fixed_model)
  720.     make_node = doc.add("make")
  721.     make_node.addText(make)
  722.     model_node = doc.add("model")
  723.     model_node.addText(stripped_model)
  724.     url_node = doc.add("url")
  725.     url_node.addText("http://www.hp.com")
  726.     
  727.     lang_node = doc.add("lang")
  728.     lang_node.add("pcl", level="3")
  729.         
  730.     if postscriptppd:
  731.         # Postscript
  732.         ps_node = lang_node.add("postscript", level="2")
  733.         lang_node.add("pjl")
  734.         ppd_node = ps_node.add("ppd")
  735.         ppd_node.addText(postscriptppd)
  736.         charset_node = lang_node.add("charset")
  737.         charset_node.addText("us-ascii")
  738.     
  739.     autodetect_node = doc.add("autodetect")
  740.     general_node = autodetect_node.add("general")
  741.     
  742.     if 1:
  743.         ieee1284_node = general_node.add("ieee1284")
  744.         ieee1284_node.addText(ieee1284)
  745.         
  746.         device_id = parseDeviceID(ieee1284)
  747.         
  748.         mfg_node = general_node.add("manufacturer")
  749.         mfg_node.addText(device_id['MFG'])
  750.         
  751.         model_node = general_node.add("model")
  752.         model_node.addText(device_id['MDL'])
  753.         
  754.         desc_node = general_node.add("description")
  755.         desc_node.addText(device_id['DES'])
  756.         
  757.         #cmdset_node = general_node.add("commandset")
  758.         #cmdset_node.addText("???")
  759.         
  760.     driver_node = autodetect_node.add("driver")
  761.     
  762.     if postscriptppd:
  763.         driver_node.addText("Postscript")
  764.     else:
  765.         driver_node.addText("hpijs")
  766.     
  767.     if verbose:
  768.         log.info(str(doc))
  769.     
  770.     output_f.write(str(doc))
  771.     
  772.     output_f.close()    
  773.  
  774.  
  775. def outputDriver(m, fixed_model, stripped_model, make, printers_node, verbose):
  776.     tech_classes = models_dict[m]['tech-class']
  777.     #print tech_classes
  778.     printer_node = printers_node.add("printer")
  779.     id_node = printer_node.add("id")
  780.     id_node.addText("printer/%s" % fixed_model)
  781.     
  782. ##    margins_node = printer_node.add("margins")
  783. ##    general_margins_node = margins_node.add("general")
  784.     
  785. ##    unit_node = general_margins_node.add("unit")
  786. ##    unit_node.addText("in")
  787. ##    
  788. ##    for tc in tech_classes:
  789. ##        if tc not in ('Undefined', 'Unsupported', 'PostScript'):
  790. ##            try:
  791. ##                margins_data = printable_areas.data[tc]
  792. ##            except KeyError:
  793. ##                continue
  794. ##            else:
  795. ##                print margins_data
  796. ##                break
  797.     
  798. ##<printer>
  799. ##   <id>printer/HP-DeskJet_350C</id><!-- HP DeskJet 350C -->
  800. ##   <functionality>
  801. ##    <maxresx>600</maxresx>
  802. ##    <maxresy>300</maxresy>
  803. ##   </functionality>
  804. ##   <ppdentry>
  805. ##     *DefaultResolution: 600dpi
  806. ##    </ppdentry>
  807. ##   <margins>
  808. ##    <general>
  809. ##     <unit>in</unit>
  810. ##     <relative />
  811. ##     <left>0.25</left>
  812. ##     <right>0.25</right>
  813. ##     <top>0.125</top>
  814. ##     <bottom>0.67</bottom>
  815. ##    </general>
  816. ##    <exception PageSize="A4">
  817. ##     <left>0.135</left>
  818. ##     <right>0.135</right>
  819. ##    </exception>
  820. ##   </margins>
  821. ##  </printer>    
  822.     
  823.     
  824.  
  825. if __name__ == '__main__':
  826.     sys.exit(main(sys.argv[1:]))
  827.  
  828.